home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / THINKC / 4_0 / READMACR.C < prev    next >
C/C++ Source or Header  |  1989-06-20  |  7KB  |  270 lines

  1.  
  2. In article <347@eldritch.hss.bu.oz>, grue@melmac.hss.bu.oz (Frobozz) writes:
  3. > In article <YYXJcay00UoL89Vkp3@andrew.cmu.edu> nf0i+@andrew.cmu.edu (Norman William Franke, III) writes:
  4. > >I would also like information on using the serial ports at speeds greater
  5. > >than 57K, or more to the point, how to read data from a MacRecorder.
  6. > >
  7. > >Norman Franke
  8. > >nf0i+@andrew.cmu.edu
  9. > Count me in too. (esp the bit about a MacRecorder)
  10. >                 Paul Dale
  11. >
  12.     What follows is some source for reading the data direct from a Mac-
  13. Recorder that was posted to this group previously.  I did not write it, so
  14. I take no credit and especially NO BLAME!
  15.  
  16. /* Written  6:18 pm  Nov 26, 1988 by palmer@tybalt.caltech.edu in
  17. uxe.cso.uiuc.edu:comp.sys.mac.programmer */
  18. Due to the large number of requests that have been posted recently, I
  19. am posting this code which reads the MacRecorder (sampling at 22 kHz).
  20.  
  21. MacRecorder comes with no programming documentation, so this is as good
  22. as it gets.  If anyone has anything better, I'd be very interested.
  23.  
  24. I don't know where the original code comes from, but I made modifications
  25. which allows it to work as an oscilloscope (on an SE or earlier machine.)
  26. The style of the original code was lousy, and I opted to maintain stylistic
  27. unity with my additions.
  28.  
  29. The core of the program is the routines which set up the port for reading
  30. an externally clocked data stream.  To understand these, you must read the
  31. Zilog SCC (Serial communications controller) data sheets.  At the MacRecorder's
  32. input rate, interrupt driven routines are infeasible, so it uses continuous
  33. polling.  This may cause data loss if other interrupts occur.
  34.  
  35. MacRecorder also transmits its data MSB first (if you understand how an SAR
  36. ADC works, you will understand why.)  This is the opposite of most serial
  37. ports, and so a translation table (included) which reverse the bit order
  38. is needed.
  39.  
  40. Here is the code:
  41. --------------------------------------------------------------
  42.  
  43. #include    <stdio.h>
  44. #include    <QuickDraw.h>
  45. #define     x1Clock        12    /* Clock mode for Scc chip */
  46. #define     x16Clock    76
  47.  
  48.  
  49. #define LENGTH 750        /* how much to read */
  50. #define WIDTH 512        /* how large the screen is */
  51. int Length = LENGTH,RealLength,x;
  52. unsigned char buffer[LENGTH];
  53. unsigned char table[256];
  54. int screentable[256];
  55. #define TOPMAR 20
  56.  
  57. void Die();
  58.  
  59. unsigned char *FindMin();
  60.  
  61. extern long *zero:0;
  62. main() 
  63. {
  64.     register unsigned char *pch;
  65.     Rect r;
  66.     long SccIn();
  67.     
  68.     int i;
  69.         
  70.     InitGraf(&thePort);
  71.     InitFonts ();
  72.     InitWindows ();
  73.     InitMenus ();
  74.     TEInit ();
  75.     InitDialogs(&Die);
  76.     InitCursor ();
  77.  
  78.     SccInit();
  79.     TableInit();
  80.     r = thePort->portBits.bounds;
  81.     PaintRect(&r);
  82.  
  83.     r.top = TOPMAR;
  84.     r.bottom = TOPMAR+256;
  85.  
  86.     for (i = 0 ; i < 256 ; i++)
  87.         screentable[i] = (table[i] + TOPMAR) * thePort->portBits.rowBytes;
  88.     do {
  89.         PenNormal();
  90.         RealLength = MySccIn(buffer, LENGTH);
  91.         pch = FindMin(buffer, LENGTH - WIDTH);
  92.         DrawCurve(pch);
  93.         if (Button()) {
  94.             SysBeep(3);
  95.             Die();
  96.         }
  97.         PaintRect(&r);
  98.     } while (RealLength>=LENGTH);
  99.     SysBeep(12);
  100. }
  101.  
  102. DrawCurve(pch)        /* works only on MacI under non-multi finder */
  103. register unsigned char *pch;
  104. {
  105.     register int byte;
  106.     register int bit;
  107.     register int *pscreentable = screentable;
  108.     register unsigned char *pscreen  = 
  109.                 (unsigned char *)(thePort->portBits.baseAddr);
  110.     
  111.     for (byte = 0 ; byte < 64 ; byte++)
  112.         for (bit = 0x100 ; bit >>= 1 ; )
  113.             pscreen[pscreentable[*pch++] + byte] ^= (char)bit;
  114. }
  115.  
  116. unsigned char *FindMin(pch, cch)
  117. unsigned char *pch;
  118. int cch;
  119. {
  120.     unsigned char *pchmin = pch;
  121.     unsigned char min = *pch;
  122.     
  123. if (cch < 0) SysBeep(3);
  124.     for ( ; --cch > 0 ; )
  125.         if (*pch++ < min) {
  126.             pchmin = pch - 1;
  127.             min = *pchmin;
  128.         }
  129.     return pchmin;
  130.  
  131. char **SccRd,**SccWr,*SccRBase,*SccWBase;    /* pointer to Scc chip */
  132. int aCtl = 2;                                /* offsets */
  133. int aData = 6;
  134. int bCtl = 0;
  135. int dData = 4;
  136. SccInit() /* initializes the Scc chip for the MacRecorder Plus */
  137.     /* for the regular MacRecorder II, replace x1Clock with x16Clock below */
  138. {    
  139.     SccRd = (char **)0x1D8;        
  140.     SccWr = (char **)0x1DC;        
  141.     SccRBase = (char *)*SccRd;    
  142.     SccWBase = (char *)*SccWr;
  143.     SccPoke(9,2);            /* NV only */
  144.                         /* following line is for MacRecorder Plus */
  145.     SccPoke(4,x1Clock);    /* 2 stop bits, Async, x1 clock mode  */
  146.     SccPoke(1,1);            /* no Rx/Tx Int, Ext Int ON (mouse) */
  147.     SccPoke(3,193);            /* initialize receiver, 8bits */
  148.     SccPoke(5,122);            /* 8bits/char, send break(for other hardware!), Tx enable */
  149.     SccPoke(11,48);            /* use TRxC as receiver clock */
  150.     SccPoke(14,1);            /* BR enable, nothing else */
  151.     SccPoke(15,8);            /* Interrupt on CD changes (mouse), turn off CTS interrupt */
  152.     SccPoke(64,64);            /* Reset Rx CRC */
  153.     SccPoke(9,10);            /* initialize master interrupt and NV */
  154. }
  155. SccPoke(n,v)        /* accesses the modem port */
  156. char n,v;
  157. {
  158.     *(SccWBase + aCtl) = n;    /* set index to register n */
  159.     *(SccWBase + aCtl) = v;    /* write v into register n */
  160. }
  161. SccPeek(n)
  162. char n;
  163. {    
  164.     *(SccWBase + aCtl) = n;        /* set index to register n */
  165.     return(*(SccRBase + aCtl));    /* retrun value in register n */
  166. }
  167. TableInit()
  168. {
  169.     MakeTable(&table[0]);
  170.     ModifyTable(&table[0]);
  171. }
  172. MakeTable(table)
  173. register char *table;
  174. {
  175.     asm    {
  176.             adda.w    #256,table
  177.             move.w    #255,D0
  178.     lp0:    move.b    D0,D1
  179.             move.w    #07,D3
  180.     lp1:    lsr.b    #01,D1
  181.             roxl.b    #01,D2
  182.             dbf        D3,@lp1
  183.             move.b    D2,-(table)
  184.             dbf        D0,@lp0
  185.         }
  186. }
  187. #ifdef FOO   /*( this is not needed if you use unsigned chars */
  188. ModifyTable(table)
  189. char *table;
  190. {
  191.     int i;
  192.     for (i=0;i<256;i++)
  193.     {
  194.         if ( table[i]>=0 ) table[i] -= 128;
  195.         else table[i] += 128 ;
  196.     }
  197. }
  198. #endif
  199. int MySccIn(dest, count)
  200. register char *dest;
  201. register int count;
  202. {
  203.     int    iCount = count;    /* actual number of bytes received */
  204.     register    char    *pSccRBase = SccRBase;
  205.     while (count-- > 0 && !Button()) {
  206.         while (0 == (pSccRBase[2] & 0x1))
  207.             if (Button())
  208.                 return (iCount - count + 1);
  209.         *dest++ = pSccRBase[6];
  210.     }
  211.     return iCount;
  212. }
  213.  
  214. long SccIn(dest,count)
  215. register char *dest;
  216. register long count;
  217. {
  218.     register    unsigned char    *Table;        /* a lookup table */
  219.     register    long    aCount;    /* actual number of bytes received */
  220.     Table = &table[0];
  221.     aCount = 0L;
  222.     asm    {
  223.         move.l  #0x9FFFF8,A0            ; /* SccRBase   */
  224. #ifdef FOO
  225.         move.l    #0xEFE1FE,A1            ; /* mouse button */
  226.         clr.l    D0
  227.     lp:    btst    #03,(A1)                ; /* mouse clicked? */
  228.         beq        @lq
  229. #else
  230.     }
  231.     lp:    if (Button())
  232.             return(aCount);
  233.     asm {
  234. #endif
  235.         btst    #00,2(A0)                ; /* SccRBase + aCtl */
  236.         beq        @lp
  237.         move.b    6(A0), D0                ; /* SccRBase + aData */
  238.         move.b    00(Table,D0), (dest)+    ; /* translate in lookup table */
  239.         addq.l    #1,aCount                ; /* one more byte received */
  240.         subq.l    #1,count
  241.         bne        @lp
  242.     lq:    nop
  243.         }
  244.     return(aCount);
  245. }
  246.  
  247. void Die()
  248. {
  249.     ExitToShell();
  250. }
  251. ----------------------------------------------------------------
  252.  
  253.         David Palmer
  254.         palmer@tybalt.caltech.edu
  255.         ...rutgers!cit-vax!tybalt.caltech.edu!palmer
  256.     "I was sad that I had no shirt, until I met a man with no torso"
  257. /* End of text from uxe.cso.uiuc.edu:comp.sys.mac.programmer */
  258.  
  259. -- 
  260. +--------------------------------------------------+
  261. Leonard Rosenthol        |  GEnie : MACgician
  262. Lazerware, inc.          |  MacNet: MACgician
  263. UUCP: svc@well.UUCP      |  ALink : D0025
  264.  
  265.  
  266.